using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace RandomRat {

	/// <summary>
	/// Delegate for handling a change event
	/// </summary>
	public delegate void ChangeEventHandler(Object sender, EventArgs e); 

	/// <summary>
	/// A control for editing list of element types.
	/// </summary>
	public class TypeControl : System.Windows.Forms.UserControl	{

		public event ChangeEventHandler Change;

		#region CONST

		const string error1 = "Two or more types are required.";

		// The list already contains 'type'
		const string msgBox1a = "The list already contains '";
		const string msgBox1b = "'";
		
		const string msgBox2 = "A type must be provided.";
		const string msgBox3 = "The list already contains this type.";

		const string msgBoxRE1 = "\nNo changes were made.";
		

		#endregion


		#region WINVARS

		protected System.Windows.Forms.GroupBox groupBox2;
		protected System.Windows.Forms.ListBox listTypes;
		protected System.Windows.Forms.Button butAddType;
		protected System.Windows.Forms.TextBox txtType;
		protected System.Windows.Forms.Button butClearTypes;
		protected System.Windows.Forms.Button butDelType;
		private System.Windows.Forms.ContextMenu contextMenu1;
		private System.Windows.Forms.MenuItem miRemove;
		private System.Windows.Forms.MenuItem miRename;
		private System.Windows.Forms.MenuItem miClear;
		private System.Windows.Forms.ErrorProvider errorProvider1;
		private System.Windows.Forms.Label labelError;
		private System.Windows.Forms.Label label1;
		private System.ComponentModel.Container components = null;

		#endregion

		public TypeControl() {
			InitializeComponent();
			label1.Text = "0";
			label1.Visible = true;
			contextMenu1.Popup += new System.EventHandler(this.contextMenu1_Popup);
		}


		#region Change event and button validation

		private void OnChange() {
			validateButtons();

			if (Change != null) {
				Change(this, new EventArgs());
			}
		}

		private void validateButtons() {
			int count = listTypes.Items.Count;
			butDelType.Enabled = (listTypes.SelectedIndex != -1);
			butClearTypes.Enabled = (count > 0);
			
			//if (count > 0) {
				label1.Visible = true;
				label1.Text = count.ToString();
			//} else {
			//	label1.Visible = false;
			//}
		}

		#endregion


		#region Main Control Functions
		
		private void addType(string text) {
			text = text.Trim();
			
			if (text != "") {
				if (!listTypes.Items.Contains(text)) {
					listTypes.Items.Add(text);
					txtType.Text = "";					
				} else {
					MessageBox.Show(this, msgBox1a + text + msgBox1b);
					txtType.SelectAll();
				}

			} else {
				txtType.SelectAll();
			}

			txtType.Focus();

			OnChange();
		}

		private void removeSelectedTypes() {
			int tempSelectedIndx = listTypes.SelectedIndex;
			ArrayList tempSelectedItems = new ArrayList(listTypes.SelectedItems);
			
			for (int i = 0; i < tempSelectedItems.Count; i++) {
				listTypes.Items.Remove(tempSelectedItems[i]);
			}

			if (listTypes.Items.Count > tempSelectedIndx) {
				listTypes.SelectedIndex = tempSelectedIndx;
				listTypes.Focus();
			} else if (listTypes.Items.Count == 0) {
				txtType.Focus();
			} else {
				listTypes.SelectedIndex = listTypes.Items.Count - 1;
				listTypes.Focus();
			}

			OnChange();
		}

		private void renameSelectedType() {
			string tempType = (string)listTypes.SelectedItem;
			if (tempType != null) {
				EditType editType = new EditType(tempType);
				editType.ShowDialog();
				
				if (editType.DialogResult == DialogResult.OK) {
					string type = editType.Type.Trim();
					
					if (tempType.CompareTo(type) != 0) {
						if (type == "") {
							MessageBox.Show(this, msgBox2 + msgBoxRE1);

						} else if (listTypes.Items.Contains(type)) {
							MessageBox.Show(this, msgBox3 + msgBoxRE1);

						} else {
							listTypes.Items[listTypes.SelectedIndex] = type;
							OnChange();
						}
					}
				}
				editType.Dispose();
			}
		}

		private void clearTypes() {
			listTypes.Items.Clear();
			OnChange();
		}

		
		#endregion


		#region Public interface

		/// <summary>
		/// Returns SetArguments compatible array of types
		/// </summary>
		/// <returns>A string[] array of types</returns>
		private string[] GetTypes() {
			string[] types = new string[listTypes.Items.Count];
			for (int i = 0; i < listTypes.Items.Count; i++) {
				types[i] = (string)listTypes.Items[i];
			}
			return types;
		}

		
		public void ClearTypes() {
			clearTypes();
		}


		public int TypeCount {
			get { return listTypes.Items.Count; }
		}

		

		#region INPUT/OUTPUT
		
		public void FillFormState(ref CriteriaFormState formState) {
			formState.Types = GetTypes();
		}

		public void FillSetArguments(ref SetArguments setArgs) {
			setArgs.Types = GetTypes();
		}

		public void LoadTypes(CriteriaFormState formState) {
			LoadTypes(formState.Types);
		}
		public void LoadTypes(ArrayList types) {
			listTypes.Items.Clear();
			foreach (string type in types) {
				listTypes.Items.Add(type);
			}
			OnChange();
		}

		public void LoadTypes(string[] types) {
			listTypes.Items.Clear();
			foreach (string type in types) {
				listTypes.Items.Add(type);
			}
			OnChange();
		}

		
		#endregion

		#region ERROR Handeling

		/// <summary>
		/// Returns whether control conforms to SetArguments
		/// </summary>
		/// <param name="showError">Show user input errors via error provider</param>
		/// <returns></returns>
		public bool IsInputValid(bool showError) {
			bool valid = listTypes.Items.Count >= 2;
		
			if (showError) {
				if (!valid) {
					errorProvider1.SetError(labelError, error1);
				} else {
					errorProvider1.SetError(labelError, "");
				}
			}

			return valid;
		}
		public void ClearErrors() {
			errorProvider1.SetError(labelError, "");
		}

		
		#endregion

		
		#endregion



		#region Basic handalers

		private void listTypes_DoubleClick(object sender, System.EventArgs e) {	
			renameSelectedType(); 
		}

		private void listTypes_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) {
			if (e.KeyCode == Keys.Delete || e.KeyCode == Keys.Back) {
				removeSelectedTypes();

			} else if (e.KeyCode == Keys.Enter) {
				renameSelectedType();
			}
		}

		private void listTypes_SelectedIndexChanged(object sender, System.EventArgs e) {
			validateButtons();
		}

		
		private void butAddType_Click(object sender, System.EventArgs e) {
			addType(txtType.Text);
		}

		private void butDelType_Click(object sender, System.EventArgs e) {
			removeSelectedTypes();
		}

		private void butClearTypes_Click(object sender, System.EventArgs e) {
			clearTypes();
			txtType.Focus();
		}


		private void txtType_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) {
			if (e.KeyChar == 13) {
				addType(txtType.Text);
			}
		}


		private void miRemove_Click(object sender, System.EventArgs e) {
			removeSelectedTypes();
		}

		private void miRename_Click(object sender, System.EventArgs e) {
			renameSelectedType();
		}

		private void miClear_Click(object sender, System.EventArgs e) {
			clearTypes();
		}

		private void contextMenu1_Popup(object sender, System.EventArgs e) {
			if (listTypes.SelectedIndex != -1) {
				miRemove.Enabled = true;
				miRename.Enabled = true;
			} else {
				miRemove.Enabled = false;
				miRename.Enabled = false;
			}

			if (listTypes.Items.Count > 0) {
				miClear.Enabled = true;
			} else {
				miClear.Enabled = false;
			}
		}


		#endregion


		#region UTIL
		protected override void Dispose( bool disposing ) {
			if( disposing )	{
				if(components != null) {
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		#region Component Designer generated code
		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent() {
			this.groupBox2 = new System.Windows.Forms.GroupBox();
			this.label1 = new System.Windows.Forms.Label();
			this.listTypes = new System.Windows.Forms.ListBox();
			this.contextMenu1 = new System.Windows.Forms.ContextMenu();
			this.miRemove = new System.Windows.Forms.MenuItem();
			this.miRename = new System.Windows.Forms.MenuItem();
			this.miClear = new System.Windows.Forms.MenuItem();
			this.butAddType = new System.Windows.Forms.Button();
			this.txtType = new System.Windows.Forms.TextBox();
			this.butClearTypes = new System.Windows.Forms.Button();
			this.butDelType = new System.Windows.Forms.Button();
			this.labelError = new System.Windows.Forms.Label();
			this.errorProvider1 = new System.Windows.Forms.ErrorProvider();
			this.groupBox2.SuspendLayout();
			this.SuspendLayout();
			// 
			// groupBox2
			// 
			this.groupBox2.Controls.AddRange(new System.Windows.Forms.Control[] {
																					this.label1,
																					this.listTypes,
																					this.butAddType,
																					this.txtType,
																					this.butClearTypes,
																					this.butDelType,
																					this.labelError});
			this.groupBox2.Location = new System.Drawing.Point(1, -1);
			this.groupBox2.Name = "groupBox2";
			this.groupBox2.Size = new System.Drawing.Size(254, 184);
			this.groupBox2.TabIndex = 24;
			this.groupBox2.TabStop = false;
			this.groupBox2.Text = "Element types";
			// 
			// label1
			// 
			this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.label1.Location = new System.Drawing.Point(220, -1);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(23, 16);
			this.label1.TabIndex = 14;
			this.label1.Text = "8";
			this.label1.TextAlign = System.Drawing.ContentAlignment.TopCenter;
			// 
			// listTypes
			// 
			this.listTypes.ContextMenu = this.contextMenu1;
			this.listTypes.Location = new System.Drawing.Point(16, 24);
			this.listTypes.Name = "listTypes";
			this.listTypes.SelectionMode = System.Windows.Forms.SelectionMode.MultiExtended;
			this.listTypes.Size = new System.Drawing.Size(120, 121);
			this.listTypes.Sorted = true;
			this.listTypes.TabIndex = 10;
			this.listTypes.KeyDown += new System.Windows.Forms.KeyEventHandler(this.listTypes_KeyDown);
			this.listTypes.DoubleClick += new System.EventHandler(this.listTypes_DoubleClick);
			this.listTypes.SelectedIndexChanged += new System.EventHandler(this.listTypes_SelectedIndexChanged);
			// 
			// contextMenu1
			// 
			this.contextMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																						 this.miRemove,
																						 this.miRename,
																						 this.miClear});
			// 
			// miRemove
			// 
			this.miRemove.Index = 0;
			this.miRemove.Text = "Remove";
			this.miRemove.Click += new System.EventHandler(this.miRemove_Click);
			// 
			// miRename
			// 
			this.miRename.Index = 1;
			this.miRename.Text = "Rename";
			this.miRename.Click += new System.EventHandler(this.miRename_Click);
			// 
			// miClear
			// 
			this.miClear.Index = 2;
			this.miClear.Text = "Clear";
			this.miClear.Click += new System.EventHandler(this.miClear_Click);
			// 
			// butAddType
			// 
			this.butAddType.Location = new System.Drawing.Point(147, 152);
			this.butAddType.Name = "butAddType";
			this.butAddType.Size = new System.Drawing.Size(88, 23);
			this.butAddType.TabIndex = 9;
			this.butAddType.Text = "Add";
			this.butAddType.Click += new System.EventHandler(this.butAddType_Click);
			// 
			// txtType
			// 
			this.txtType.Location = new System.Drawing.Point(16, 152);
			this.txtType.MaxLength = 75;
			this.txtType.Name = "txtType";
			this.txtType.Size = new System.Drawing.Size(120, 20);
			this.txtType.TabIndex = 8;
			this.txtType.Text = "";
			this.txtType.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.txtType_KeyPress);
			// 
			// butClearTypes
			// 
			this.butClearTypes.Enabled = false;
			this.butClearTypes.Location = new System.Drawing.Point(147, 96);
			this.butClearTypes.Name = "butClearTypes";
			this.butClearTypes.Size = new System.Drawing.Size(88, 24);
			this.butClearTypes.TabIndex = 11;
			this.butClearTypes.Text = "Clear";
			this.butClearTypes.Click += new System.EventHandler(this.butClearTypes_Click);
			// 
			// butDelType
			// 
			this.butDelType.Enabled = false;
			this.butDelType.Location = new System.Drawing.Point(147, 120);
			this.butDelType.Name = "butDelType";
			this.butDelType.Size = new System.Drawing.Size(88, 23);
			this.butDelType.TabIndex = 12;
			this.butDelType.Text = "Remove";
			this.butDelType.Click += new System.EventHandler(this.butDelType_Click);
			// 
			// labelError
			// 
			this.labelError.BackColor = System.Drawing.Color.Transparent;
			this.labelError.Location = new System.Drawing.Point(100, 25);
			this.labelError.Name = "labelError";
			this.labelError.Size = new System.Drawing.Size(36, 20);
			this.labelError.TabIndex = 13;
			// 
			// errorProvider1
			// 
			this.errorProvider1.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.NeverBlink;
			this.errorProvider1.DataMember = null;
			// 
			// TypeControl
			// 
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.groupBox2});
			this.Name = "TypeControl";
			this.Size = new System.Drawing.Size(256, 184);
			this.groupBox2.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion
		#endregion
	
	}
}
